//
//  NSObject+LBStore.m
//  app
//
//  Created by LINAICAI on 16/6/2.
//  Copyright © 2016年 广东联结电子商务有限公司. All rights reserved.
//

#import "NSObject+LBStore.h"
#import <objc/runtime.h>
#import <objc/message.h>
/**
 *  目录路径
 */
static const NSString *doc = @"Models";
@implementation NSObject (LBStore)
- (__kindof NSObject *)load{
    NSData *data = [[NSData alloc] initWithContentsOfFile:[self getFilePathWithModelKey:NSStringFromClass(self.class)]];
    //解档辅助类
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    //解档出数据模型
    unsigned int outCount = 0;
    Ivar *ivars = class_copyIvarList([self class], &outCount);
    
    for (unsigned int i = 0; i < outCount; ++i) {
        Ivar ivar = ivars[i];
        
        // 获取成员变量名
        const void *name = ivar_getName(ivar);
        NSString *ivarName = [NSString stringWithUTF8String:name];
        // 去掉成员变量的下划线
        ivarName = [ivarName substringFromIndex:1];
        // 生成setter格式
        NSString *setterName = ivarName;
        // 那么一定是字母开头
        if (![setterName hasPrefix:@"_"]) {
            NSString *firstLetter = [NSString stringWithFormat:@"%c", [setterName characterAtIndex:0]];
            setterName = [setterName substringFromIndex:1];
            setterName = [NSString stringWithFormat:@"%@%@", firstLetter.uppercaseString, setterName];
        }
        setterName = [NSString stringWithFormat:@"set%@:", setterName];
        // 获取getter方法
        SEL setter = NSSelectorFromString(setterName);
        if ([self respondsToSelector:setter]) {
            const void *typeEncoding = ivar_getTypeEncoding(ivar);
            NSString *type = [NSString stringWithUTF8String:typeEncoding];
            
            
            // const void *
            if ([type isEqualToString:@"r^v"]) {
                NSString *value = [unarchiver decodeObjectForKey:ivarName];
                if (value) {
                    ((void (*)(id, SEL, const void *))objc_msgSend)(self, setter, value.UTF8String);
                }
                
                continue;
            }
            // int
            else if ([type isEqualToString:@"i"]) {
                NSNumber *value = [unarchiver decodeObjectForKey:ivarName];
                if (value != nil) {
                    ((void (*)(id, SEL, int))objc_msgSend)(self, setter, [value intValue]);
                }
                continue;
            } else if ([type isEqualToString:@"f"]) {
                NSNumber *value = [unarchiver decodeObjectForKey:ivarName];
                if (value != nil) {
                    ((void (*)(id, SEL, float))objc_msgSend)(self, setter, [value floatValue]);
                }
                continue;
            }
            
            // object
            id value = [unarchiver decodeObjectForKey:ivarName];
            if (value != nil) {
                ((void (*)(id, SEL, id))objc_msgSend)(self, setter, value);
            }
        }
    }
    
    free(ivars);
    //关闭解档
    [unarchiver finishDecoding];
    return self;
    
}
//保存信息
- (BOOL)save{
    NSMutableData *data = [[NSMutableData alloc] init];
    //创建归档辅助类
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    //编码
    unsigned int outCount = 0;
    Ivar *ivars = class_copyIvarList([self class], &outCount);
    
    for (unsigned int i = 0; i < outCount; ++i) {
        Ivar ivar = ivars[i];
        
        // 获取成员变量名
        const void *name = ivar_getName(ivar);
        NSString *ivarName = [NSString stringWithUTF8String:name];
        // 去掉成员变量的下划线
        ivarName = [ivarName substringFromIndex:1];
        
        // 获取getter方法
        SEL getter = NSSelectorFromString(ivarName);
        
        if ([self respondsToSelector:getter]) {
            const void *typeEncoding = ivar_getTypeEncoding(ivar);
            NSString *type = [NSString stringWithUTF8String:typeEncoding];
            
            // const void *
            if ([type isEqualToString:@"r^v"]) {
                const char *value = ((const void *(*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
                NSString *utf8Value = [NSString stringWithUTF8String:value];
                [archiver encodeObject:utf8Value forKey:ivarName];
                continue;
            }
            // int
            else if ([type isEqualToString:@"i"]) {
                int value = ((int (*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
                [archiver encodeObject:@(value)forKey:ivarName];
                continue;
            }
            // float
            else if ([type isEqualToString:@"f"]) {
                float value = ((float (*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
                [archiver encodeObject:@(value)forKey:ivarName];
                continue;
            }
            
            id value = ((id (*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
            if (value != nil && [value respondsToSelector:@selector(encodeWithCoder:)]) {
                [archiver encodeObject:value forKey:ivarName];
            }
        }
    }
    
    free(ivars);
    
    //结束编码
    [archiver finishEncoding];
    //写入
    return [data writeToFile:[self getFilePathWithModelKey:NSStringFromClass(self.class)] atomically:YES];
    
}
//得到Document目录
-(NSString *) getFilePathWithModelKey:(NSString *)modelkey
{
    NSArray *array =  NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[array objectAtIndex:0] stringByAppendingPathComponent:modelkey];
}
- (NSString *)doc{
    NSString *paths = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    NSString *path = [paths stringByAppendingString:[NSString stringWithFormat:@"/%@",doc]];
    return path;
}
@end
